#    Tichy
#
#    copyright 2008 Guillaume Chereau (charlie137@gmail.com)
#
#    This file is part of Tichy.
#
#    Tichy is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Tichy is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Tichy.  If not, see <http://www.gnu.org/licenses/>.

__docformat__ = 'reStructuredText'

from object import Object

from item import Item, ItemMetaClass

import logging
logger = logging.getLogger('Service')


class ServiceMetaClass(ItemMetaClass):
    """The meta class for Service class"""

    def __init__(cls, name, bases, dict):
        """Register a service class
        """
        super(ServiceMetaClass, cls).__init__(name, bases, dict)
        cls._Service__instance = None


class ServiceUnusable(Exception):
    """Exception raised by a service if it not usable

    The service module will then try to use an other service.
    """

    def __init__(self, msg=None):
        super(ServiceUnusable, self).__init__(msg)


class Service(Item):

    __metaclass__ = ServiceMetaClass
    # This attribute is a dict of list : (service_name -> [service_cls])
    __all_services = {}

    @classmethod
    def _get_base_service(cls):
        """
        Return the first parent class that is a direct descendant of the
        Service class
        """
        if cls.__base__ is Service:
            return cls
        return cls.__base__._get_base_service()

    @staticmethod
    def init_all():
        # We iterate starting from the most specific services
        for cls in reversed(Service.subclasses):
            if cls._get_base_service().__instance:
                continue
            try:
                logger.debug("try to create service %s", cls)
                cls.__instance = cls()
                logger.debug("create service %s done", cls)
            except ServiceUnusable:
                logger.debug("service %s unusable", cls)
                continue
            base = cls.__base__
            while issubclass(base, Service):
                base.__instance = cls.__instance
                base = base.__base__

    @classmethod
    def get(cls):
        assert cls.__instance is not None
        return cls.__instance
